package main

import "fmt"

/*
面向对象

	go语句只支持封装，不支持继承和多态
	go语言没有class 只有struct
*/
type TreeNode struct {
	Value       int
	Left, Right *TreeNode
}

func (root *TreeNode) traverse() {
	if root == nil {
		return
	}

	root.Left.traverse()
	fmt.Println(root.Value)
	root.Right.traverse()
}

// 工厂函数         自定义工厂函数     注意返回了局部变量的地址！
// 局部变量构建是 在  栈   还是 堆，——————————————》    这个不需要知道   因为有  gc
func createNode(value int) *TreeNode {
	// 局部变量
	return &TreeNode{Value: value}
}

// 遍历          为结构定义方法     显示定义和命名方法接受者
func (node TreeNode) print() {
	fmt.Print(node.Value, " ")
}

// 传值      (这里的指针是后面加上去的 这样就可以修改值了)
// 使用指针作为方法接收者            只有使用指针才可以改变结构内容     nil指针也可以调用方法！
func (node *TreeNode) setValue(value int) {
	if node == nil {
		fmt.Println("Setting value to nil node. Ignored.")
		return
	}
	node.Value = value
}

// loop  func
func (node *TreeNode) loop() {
	if node == nil {
		return
	}
	node.Left.loop()
	node.print()
	node.Right.loop()
}

func main() {
	var root TreeNode
	fmt.Println(root)
	root = TreeNode{Value: 3}
	root.Left = &TreeNode{}
	root.Right = &TreeNode{5, nil, nil}
	root.Right.Left = new(TreeNode)
	root.Left.Right = createNode(2)

	nodes := []TreeNode{
		{Value: 3},
		{},
		{6, nil, nil},
	}
	fmt.Println(nodes)

	root.print() // 3
	root.Right.Left.setValue(4)
	root.Right.Left.print() // 0

	root.print()
	root.setValue(100)

	pRoot := &root
	pRoot.print()
	pRoot.setValue(200)
	pRoot.print()

	var qRoot *TreeNode
	qRoot.setValue(200)
	qRoot = &root
	qRoot.setValue(300)
	qRoot.print()

	root.loop()
	/*
		值接受者vs指针接收者
		- 要改变内容必须使用指针接收者
		- 结构过大也考虑使用指针接收者
		- 一致性： 如有指针接收者，最好都是指针接收者
	*/
	/*
		值接收者  是go语言特有
		值/指针接收者均可接受值/指针
	*/
}
